
package com.tongyao.service.impl;

import com.tongyao.domain.req.WeixinQrCodeReq;
import com.tongyao.domain.res.WeixinQrCodeRes;
import com.tongyao.domain.res.WeixinTokenRes;
import com.tongyao.domain.vo.WeixinTemplateMessageVO;
import com.tongyao.service.ILoginService;
import com.tongyao.service.weixin.IWeixinApiService;
import com.google.common.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import retrofit2.Call;
import retrofit2.Response;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Fuzhengwei bugstack.cn @小傅哥
 * @description 微信服务
 * @create 2024-09-28 13:46
 */
@Service
public class WeixinLoginServiceImpl implements ILoginService {

    private static final Logger logger = LoggerFactory.getLogger(WeixinLoginServiceImpl.class);

    @Value("${weixin.config.app-id}")
    private String appid;
    @Value("${weixin.config.app-secret}")
    private String appSecret;
    @Value("${weixin.config.template_id}")
    private String template_id;

    @Resource
    private Cache<String, String> weixinAccessToken;
    @Resource
    private IWeixinApiService weixinApiService;
    @Resource
    private Cache<String, String> openidToken;

    @Override
    public String createQrCodeTicket() throws Exception {
        // 1. 获取 accessToken
        String accessToken = weixinAccessToken.getIfPresent(appid);
        if (null == accessToken) {
            logger.info("AccessToken not found in cache, fetching from WeChat API...");
            Call<WeixinTokenRes> call = weixinApiService.getToken("client_credential", appid, appSecret);
            Response<WeixinTokenRes> response = call.execute();
            if (!response.isSuccessful()) {
                logger.error("Failed to fetch accessToken from WeChat API: {}", response.errorBody().string());
                throw new RuntimeException("Failed to fetch accessToken from WeChat API");
            }
            WeixinTokenRes weixinTokenRes = response.body();
            if (weixinTokenRes == null) {
                logger.error("WeChat API returned null response for accessToken");
                throw new RuntimeException("WeChat API returned null response for accessToken");
            }
            accessToken = weixinTokenRes.getAccess_token();
            if (accessToken == null) {
                logger.error("WeChat API returned null accessToken: {}", weixinTokenRes);
                throw new RuntimeException("WeChat API returned null accessToken");
            }
            weixinAccessToken.put(appid, accessToken);
            logger.info("Fetched and cached accessToken: {}", accessToken);
        } else {
            logger.info("Using cached accessToken: {}", accessToken);
        }

        // 2. 生成 ticket
        WeixinQrCodeReq weixinQrCodeReq = WeixinQrCodeReq.builder()
                .expire_seconds(2592000)
                .action_name(WeixinQrCodeReq.ActionNameTypeVO.QR_SCENE.getCode())
                .action_info(WeixinQrCodeReq.ActionInfo.builder()
                        .scene(WeixinQrCodeReq.ActionInfo.Scene.builder()
                                .scene_id(100601)
                                .build())
                        .build())
                .build();

        logger.info("Creating QR code with request: {}", weixinQrCodeReq);
        Call<WeixinQrCodeRes> call = weixinApiService.createQrCode(accessToken, weixinQrCodeReq);
        Response<WeixinQrCodeRes> response = call.execute();
        if (!response.isSuccessful()) {
            logger.error("Failed to create QR code: {}", response.errorBody().string());
            throw new RuntimeException("Failed to create QR code");
        }
        WeixinQrCodeRes weixinQrCodeRes = response.body();
        if (weixinQrCodeRes == null) {
            logger.error("WeChat API returned null response for QR code");
            throw new RuntimeException("WeChat API returned null response for QR code");
        }
        String ticket = weixinQrCodeRes.getTicket();
        if (ticket == null) {
            logger.error("WeChat API returned null ticket: {}", weixinQrCodeRes);
            throw new RuntimeException("WeChat API returned null ticket");
        }
        logger.info("Created QR code ticket: {}", ticket);
        return ticket;
    }

    @Override
    public String checkLogin(String ticket) {
        String openid = openidToken.getIfPresent(ticket);
        if (openid == null) {
            logger.warn("No openid found for ticket: {}", ticket);
        } else {
            logger.info("Found openid for ticket {}: {}", ticket, openid);
        }
        return openid;
    }

    @Override
    public void saveLoginState(String ticket, String openid) throws IOException {
        openidToken.put(ticket, openid);
        logger.info("Saved login state for ticket {}: openid {}", ticket, openid);

        // 1. 获取 accessToken 【实际业务场景，按需处理下异常】
        String accessToken = weixinAccessToken.getIfPresent(appid);
        if (null == accessToken) {
            logger.info("AccessToken not found in cache, fetching from WeChat API...");
            Call<WeixinTokenRes> call = weixinApiService.getToken("client_credential", appid, appSecret);
            Response<WeixinTokenRes> response = call.execute();
            if (!response.isSuccessful()) {
                logger.error("Failed to fetch accessToken from WeChat API: {}", response.errorBody().string());
                throw new RuntimeException("Failed to fetch accessToken from WeChat API");
            }
            WeixinTokenRes weixinTokenRes = response.body();
            if (weixinTokenRes == null) {
                logger.error("WeChat API returned null response for accessToken");
                throw new RuntimeException("WeChat API returned null response for accessToken");
            }
            accessToken = weixinTokenRes.getAccess_token();
            if (accessToken == null) {
                logger.error("WeChat API returned null accessToken: {}", weixinTokenRes);
                throw new RuntimeException("WeChat API returned null accessToken");
            }
            weixinAccessToken.put(appid, accessToken);
            logger.info("Fetched and cached accessToken: {}", accessToken);
        } else {
            logger.info("Using cached accessToken: {}", accessToken);
        }

        // 2. 发送模板消息
        Map<String, Map<String, String>> data = new HashMap<>();
        WeixinTemplateMessageVO.put(data, WeixinTemplateMessageVO.TemplateKey.USER, openid);

        WeixinTemplateMessageVO templateMessageDTO = new WeixinTemplateMessageVO(openid, template_id);
        templateMessageDTO.setUrl("https://gaga.plus");
        templateMessageDTO.setData(data);

        logger.info("Sending template message with data: {}", templateMessageDTO);
        Call<Void> call = weixinApiService.sendMessage(accessToken, templateMessageDTO);
        Response<Void> response = call.execute();
        if (!response.isSuccessful()) {
            logger.error("Failed to send template message: {}", response.errorBody().string());
            throw new RuntimeException("Failed to send template message");
        }
        logger.info("Template message sent successfully");
    }
}